#include <iostream>
#include <fstream>
#include <string>
#include <sys/mman.h>
#include <unistd.h>
#include <dlfcn.h>
#include <thread>

void LoadBinaryFromFile(const std::string& file_name, std::string* data) {
    std::ifstream fs(file_name, std::ios::in | std::ios::binary);
    // get its size:
    fs.seekg(0, std::ios::end);
    size_t size = static_cast<size_t>(fs.tellg());
    fs.seekg(0, std::ios::beg);
    data->resize(size);
    fs.read(&(*data)[0], size);
}

void PrintFree(const char* msg)
{
    std::cout<< msg << std::endl;
    system("free");
    std::cout<< "\n\n" << std::endl;
}

int main() {
    PrintFree("Before memfd_create:");

    int shm_fd = memfd_create("dlopen_in_mem", 0);
    std::cout<< "shm_fd = " << shm_fd << std::endl;
    PrintFree("after memfd_create, before write:");

    std::string strSoData;
    LoadBinaryFromFile("libsub.so", &strSoData);
    write(shm_fd, &strSoData[0], strSoData.size());
    PrintFree("after write, before dlopen:");

    char path[1024]{0};
    snprintf(path, 1023, "/proc/%d/fd/%d", getpid(), shm_fd);

    void *pHandle = dlopen(path, RTLD_NOW);

    PrintFree("after dlopen, before close:");
    close(shm_fd);
    PrintFree("after close:");
   
    if (NULL == pHandle)
    {
        std::cout<< "dlopen error: " << dlerror() << std::endl;
    }
    else
    {
        typedef void (*pFun)(void);
        while (1)
        {
            pFun fun = (pFun)dlsym(pHandle, "subfun");
            fun();
            std::this_thread::sleep_for(std::chrono::seconds(1));
        }
        dlclose(pHandle);
    }
}